package cn.itcast;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class fastjson的使用_JSONObject与JSONArray的使用 {



    /*
         fastjson的使用_JSONObject与JSONArray的使用:

         🔴1.使用JOSN.parseObject(jsonstr,Feature.OrderedField)解析jsonstr生成JSONObject对象,它对应了jsonstr的结构

                或者HotelDoc hotelDoc = JSON.parseObject(jsonStr, HotelDoc.class);
                直接解析成对应实体类对象

         🔴2.使用jsonObject.getJSONObject("key值")得到对应键对应的值,该值仍然是一个JSONObject对象,如此便可以一层一层获得jsonstr结构中的内容

         🔴3.到达jsonstr结构最里层后,

              🟢3.1 如果jsonstr中是[],可以使用jsonObject.getJSONArray("key值")得到JSONArray对象,可以直接for循环该队列,
              也可以使用List<Weather> forecastList = forecast.toJavaList(Weather.class)转成List<Weather>类型,
              甚至还可以使用Stream流操作,打开流,然后用map将JSONArray中每个Object转成Weather,再用收集方法collect(Collectors.toList())将流操作结果收集到List<Weather>类型,代码如下:

               List<Weather> weatherList2 = forecast.stream().map(new Function<Object, Weather>() {//表示要将Object泛型流转换成Weather泛型流
                     @Override
                     public Weather apply(Object o) {
                         JSONObject temp = (JSONObject) o;
                         return temp.toJavaObject(Weather.class);
                     }
                 }).collect(Collectors.toList());

              🟢3.2 如果jsonstr中是单个值,可以使用jsonObject.getString("key值")得到String类型

              🟢3.3 如果jsonstr中是个对象,即里层仍然是JSONObject对象,那么直接使用CityInfo cityInfo1 = cityInfo.toJavaObject(CityInfo.class)根据与jsonstr结构对应的实体类CityInfo转换成CityInfo对象即可
         */


    @Test
    public void test01() {

        /*  http://t.weather.itboy.net/api/weather/city/101110101  */

        /**
         * {
         * 	"message": "success感谢又拍云(upyun.com)提供CDN赞助",
         * 	"status": 200,
         * 	"date": "20230528",
         * 	"time": "2023-05-28 13:55:12",
         * 	"cityInfo": {
         * 		"city": "西安市",
         * 		"citykey": "101110101",
         * 		"parent": "陕西",
         * 		"updateTime": "09:46"
         *        },
         * 	"data": {
         * 		"shidu": "100%",
         * 		"pm25": 12.0,
         * 		"pm10": 6.0,
         * 		"quality": "优",
         * 		"wendu": "19",
         * 		"ganmao": "各类人群可自由活动",
         * 		"forecast": [{
         * 			"date": "28",
         * 			"high": "高温 18℃",
         * 			"low": "低温 15℃",
         * 			"ymd": "2023-05-28",
         * 			"week": "星期日",
         * 			"sunrise": "05:34",
         * 			"sunset": "19:48",
         * 			"aqi": 34,
         * 			"fx": "南风",
         * 			"fl": "1级",
         * 			"type": "小雨",
         * 			"notice": "雨虽小，注意保暖别感冒"
         *        }, {
         * 			"date": "29",
         * 			"high": "高温 21℃",
         * 			"low": "低温 16℃",
         * 			"ymd": "2023-05-29",
         * 			"week": "星期一",
         * 			"sunrise": "05:34",
         * 			"sunset": "19:49",
         * 			"aqi": 27,
         * 			"fx": "东北风",
         * 			"fl": "1级",
         * 			"type": "小雨",
         * 			"notice": "雨虽小，注意保暖别感冒"
         *        }],
         * 		"yesterday": {
         * 			"date": "27",
         * 			"high": "高温 18℃",
         * 			"low": "低温 14℃",
         * 			"ymd": "2023-05-27",
         * 			"week": "星期六",
         * 			"sunrise": "05:35",
         * 			"sunset": "19:47",
         * 			"aqi": 29,
         * 			"fx": "西南风",
         * 			"fl": "1级",
         * 			"type": "中雨",
         * 			"notice": "记得随身携带雨伞哦"
         *        }
         *    }
         * }
         */

        String jsonstr = "{\n" +
                "\t\"message\": \"success感谢又拍云(upyun.com)提供CDN赞助\",\n" +
                "\t\"status\": 200,\n" +
                "\t\"date\": \"20230528\",\n" +
                "\t\"time\": \"2023-05-28 13:55:12\",\n" +
                "\t\"cityInfo\": {\n" +
                "\t\t\"city\": \"西安市\",\n" +
                "\t\t\"citykey\": \"101110101\",\n" +
                "\t\t\"parent\": \"陕西\",\n" +
                "\t\t\"updateTime\": \"09:46\"\n" +
                "\t},\n" +
                "\t\"data\": {\n" +
                "\t\t\"shidu\": \"100%\",\n" +
                "\t\t\"pm25\": 12.0,\n" +
                "\t\t\"pm10\": 6.0,\n" +
                "\t\t\"quality\": \"优\",\n" +
                "\t\t\"wendu\": \"19\",\n" +
                "\t\t\"ganmao\": \"各类人群可自由活动\",\n" +
                "\t\t\"forecast\": [{\n" +
                "\t\t\t\"date\": \"28\",\n" +
                "\t\t\t\"high\": \"高温 18℃\",\n" +
                "\t\t\t\"low\": \"低温 15℃\",\n" +
                "\t\t\t\"ymd\": \"2023-05-28\",\n" +
                "\t\t\t\"week\": \"星期日\",\n" +
                "\t\t\t\"sunrise\": \"05:34\",\n" +
                "\t\t\t\"sunset\": \"19:48\",\n" +
                "\t\t\t\"aqi\": 34,\n" +
                "\t\t\t\"fx\": \"南风\",\n" +
                "\t\t\t\"fl\": \"1级\",\n" +
                "\t\t\t\"type\": \"小雨\",\n" +
                "\t\t\t\"notice\": \"雨虽小，注意保暖别感冒\"\n" +
                "\t\t}, {\n" +
                "\t\t\t\"date\": \"29\",\n" +
                "\t\t\t\"high\": \"高温 21℃\",\n" +
                "\t\t\t\"low\": \"低温 16℃\",\n" +
                "\t\t\t\"ymd\": \"2023-05-29\",\n" +
                "\t\t\t\"week\": \"星期一\",\n" +
                "\t\t\t\"sunrise\": \"05:34\",\n" +
                "\t\t\t\"sunset\": \"19:49\",\n" +
                "\t\t\t\"aqi\": 27,\n" +
                "\t\t\t\"fx\": \"东北风\",\n" +
                "\t\t\t\"fl\": \"1级\",\n" +
                "\t\t\t\"type\": \"小雨\",\n" +
                "\t\t\t\"notice\": \"雨虽小，注意保暖别感冒\"\n" +
                "\t\t}],\n" +
                "\t\t\"yesterday\": {\n" +
                "\t\t\t\"date\": \"27\",\n" +
                "\t\t\t\"high\": \"高温 18℃\",\n" +
                "\t\t\t\"low\": \"低温 14℃\",\n" +
                "\t\t\t\"ymd\": \"2023-05-27\",\n" +
                "\t\t\t\"week\": \"星期六\",\n" +
                "\t\t\t\"sunrise\": \"05:35\",\n" +
                "\t\t\t\"sunset\": \"19:47\",\n" +
                "\t\t\t\"aqi\": 29,\n" +
                "\t\t\t\"fx\": \"西南风\",\n" +
                "\t\t\t\"fl\": \"1级\",\n" +
                "\t\t\t\"type\": \"中雨\",\n" +
                "\t\t\t\"notice\": \"记得随身携带雨伞哦\"\n" +
                "\t\t}\n" +
                "\t}\n" +
                "}";


//        JSONObject jsonObject = JSON.parseObject(jsonstr);//使用com.alibaba.fastjson包中的JSON类解析json字符串得到JSONObject
//        但是会发现生成的JSONObject与原jsonstr结构顺序不一致,因为默认使用的是HashMap存放数据,而hashmap是数组加链表结构，根据key的hash算法确定在数组中的位置，当发生hash冲突的时候，根据二叉树或者红黑树构成链表,所以生成的JSONObject对象是无序的.如果要实现转换前的数据顺序与转换后的数据顺序一致，可以使用
//        JSON.parseObject(jsonstr, Feature.OrderedField)
//        此时会使用LinkedHashMap，LinkedHashMap的内部维持了一个双向链表，保存了数据的插入顺序，遍历时，先得到的数据便是先插入的。


        JSONObject jsonObject = JSON.parseObject(jsonstr, Feature.OrderedField);//带上枚举量Feature.OrderedField可以使得生成的JSONObject与原jsonstr结构顺序一致
        System.out.println("jsonObject:" + jsonObject);
        /*jsonObject:{"message":"success感谢又拍云(upyun.com)提供CDN赞助","status":200,"date":"20230528","time":"2023-05-28 13:55:12","cityInfo":{"city":"西安市","citykey":"101110101","parent":"陕西","updateTime":"09:46"},"data":{"shidu":"100%","pm25":12.0,"pm10":6.0,"quality":"优","wendu":"19","ganmao":"各类人群可自由活动","forecast":[{"date":"28","high":"高温 18℃","low":"低温 15℃","ymd":"2023-05-28","week":"星期日","sunrise":"05:34","sunset":"19:48","aqi":34,"fx":"南风","fl":"1级","type":"小雨","notice":"雨虽小，注意保暖别感冒"},{"date":"29","high":"高温 21℃","low":"低温 16℃","ymd":"2023-05-29","week":"星期一","sunrise":"05:34","sunset":"19:49","aqi":27,"fx":"东北风","fl":"1级","type":"小雨","notice":"雨虽小，注意保暖别感冒"}],"yesterday":{"date":"27","high":"高温 18℃","low":"低温 14℃","ymd":"2023-05-27","week":"星期六","sunrise":"05:35","sunset":"19:47","aqi":29,"fx":"西南风","fl":"1级","type":"中雨","notice":"记得随身携带雨伞哦"}}}*/


        JSONObject cityInfo = jsonObject.getJSONObject("cityInfo");//根据键,获取对应的值
        CityInfo cityInfo1 = cityInfo.toJavaObject(CityInfo.class);
        System.out.println("cityInfo:" + cityInfo);
        /*cityInfo:{"city":"西安市","citykey":"101110101","parent":"陕西","updateTime":"09:46"}*/
        System.out.println("cityInfo1:" + cityInfo1);
        /*cityInfo1:CityInfo(city=西安市, citykey=101110101, parent=陕西, updateTime=09:46)*/

        JSONObject data = jsonObject.getJSONObject("data");
        System.out.println("data:" + data);
        /*data:{"shidu":"100%","pm25":12.0,"pm10":6.0,"quality":"优","wendu":"19","ganmao":"各类人群可自由活动","forecast":[{"date":"28","high":"高温 18℃","low":"低温 15℃","ymd":"2023-05-28","week":"星期日","sunrise":"05:34","sunset":"19:48","aqi":34,"fx":"南风","fl":"1级","type":"小雨","notice":"雨虽小，注意保暖别感冒"},{"date":"29","high":"高温 21℃","low":"低温 16℃","ymd":"2023-05-29","week":"星期一","sunrise":"05:34","sunset":"19:49","aqi":27,"fx":"东北风","fl":"1级","type":"小雨","notice":"雨虽小，注意保暖别感冒"}],"yesterday":{"date":"27","high":"高温 18℃","low":"低温 14℃","ymd":"2023-05-27","week":"星期六","sunrise":"05:35","sunset":"19:47","aqi":29,"fx":"西南风","fl":"1级","type":"中雨","notice":"记得随身携带雨伞哦"}}*/

        String ganmao = data.getString("ganmao");
        System.out.println("ganmao:" + ganmao);
        /*ganmao:各类人群可自由活动*/

        JSONArray forecast = data.getJSONArray("forecast");//forecast是个JSON数组
        System.out.println("forecast:" + forecast);
        /*forecast:[{"date":"28","high":"高温 18℃","low":"低温 15℃","ymd":"2023-05-28","week":"星期日","sunrise":"05:34","sunset":"19:48","aqi":34,"fx":"南风","fl":"1级","type":"小雨","notice":"雨虽小，注意保暖别感冒"},{"date":"29","high":"高温 21℃","low":"低温 16℃","ymd":"2023-05-29","week":"星期一","sunrise":"05:34","sunset":"19:49","aqi":27,"fx":"东北风","fl":"1级","type":"小雨","notice":"雨虽小，注意保暖别感冒"}]*/

        List<Weather> forecastList = forecast.toJavaList(Weather.class);
        System.out.println("forecastList:" + forecastList);
        /*forecastList:[Weather(date=28, high=高温 18℃, low=低温 15℃, ymd=2023-05-28, week=星期日, sunrise=05:34, sunset=19:48, aqi=34, fx=南风, fl=1级, type=小雨, notice=雨虽小，注意保暖别感冒), Weather(date=29, high=高温 21℃, low=低温 16℃, ymd=2023-05-29, week=星期一, sunrise=05:34, sunset=19:49, aqi=27, fx=东北风, fl=1级, type=小雨, notice=雨虽小，注意保暖别感冒)]*/


//      遍历JSONArray获取数据存入List中的方式
//      方式一：
        List<Weather> weatherList1 = new ArrayList<>();
        for (Object o : forecast) {
            JSONObject temp = (JSONObject) o;
            Weather weather = temp.toJavaObject(Weather.class);
            System.out.println("weather:" + weather);
            /*weather:Weather(date=28, high=高温 18℃, low=低温 15℃, ymd=2023-05-28, week=星期日, sunrise=05:34, sunset=19:48, aqi=34, fx=南风, fl=1级, type=小雨, notice=雨虽小，注意保暖别感冒)*/
            /*weather:Weather(date=29, high=高温 21℃, low=低温 16℃, ymd=2023-05-29, week=星期一, sunrise=05:34, sunset=19:49, aqi=27, fx=东北风, fl=1级, type=小雨, notice=雨虽小，注意保暖别感冒)*/
            weatherList1.add(weather);
        }
        System.out.println("weatherList:" + weatherList1);
        /*weatherList:[Weather(date=28, high=高温 18℃, low=低温 15℃, ymd=2023-05-28, week=星期日, sunrise=05:34, sunset=19:48, aqi=34, fx=南风, fl=1级, type=小雨, notice=雨虽小，注意保暖别感冒), Weather(date=29, high=高温 21℃, low=低温 16℃, ymd=2023-05-29, week=星期一, sunrise=05:34, sunset=19:49, aqi=27, fx=东北风, fl=1级, type=小雨, notice=雨虽小，注意保暖别感冒)]*/


//      方式二：
        List<Weather> weatherList2 = forecast.stream().map(new Function<Object, Weather>() {//表示要将Object泛型流转换成Weather泛型流
            @Override
            public Weather apply(Object o) {
                JSONObject temp = (JSONObject) o;
                return temp.toJavaObject(Weather.class);
            }
        }).collect(Collectors.toList());//表示收集到List中,该List集合可以正常添加数据,删除,修改,获取
        System.out.println("weatherList2:" + weatherList2);
        //weatherList2:[Weather(date=28, high=高温 18℃, low=低温 15℃, ymd=2023-05-28, week=星期日, sunrise=05:34, sunset=19:48, aqi=34, fx=南风, fl=1级, type=小雨, notice=雨虽小，注意保暖别感冒), Weather(date=29, high=高温 21℃, low=低温 16℃, ymd=2023-05-29, week=星期一, sunrise=05:34, sunset=19:49, aqi=27, fx=东北风, fl=1级, type=小雨, notice=雨虽小，注意保暖别感冒)]
    }
}
